<?php
defined('OA_LIB_PATH') || define('OA_LIB_PATH', '/opt/op/OALib');
defined('OPEN_LIB_PATH') || define('OPEN_LIB_PATH', '/opt/op/OpenLib');

require_once 'OaLogic.php';
require_once OPEN_LIB_PATH . '/open/models/OaAppModel.php';
require_once OPEN_LIB_PATH . '/open/models/OaAppServerModel.php';
require_once OPEN_LIB_PATH . '/open/models/OaAppConfigOrderModel.php';

class OaAppServerLogic extends OaLogic
{

    /**
     * 拷贝连调环境服务器配置到正式环境
     * @param int $appId
     * @param string $type all表示登录、发货服务器都拷贝，login表示只拷贝登录服务器，pay表示只拷贝发货服务器 
     * @return boolean
     */
    public static function copyTestConfigToProduction($appId, $type = 'all')
    {
        $logger = self::getLogger();
        $appServerInTest = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $appServerInProduction = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_PRODUCTION, $logger);
        
        $areas = $appServerInTest->getAppAreas($appId);
        foreach ($areas as $area) {
            $areaId = $appServerInProduction->addArea($appId, $area['name'], $area['idc_type'], 
                array(
                    'area_code' => $area['area_code'],
                    'creator' => $area['creator'],
                    'status' => $area['status']
                ));
            if ($areaId === false) {
                $logger->warning("copy area failed: area-{$area['id']}, error-" . 
                    $appServerInProduction->getErrorMessage());
                continue;
            }
            $appServerInTest->modifyArea($area['id'], array(
            	'map_id' => $areaId
            ));
            $groups = $appServerInTest->getAreaGroups($area['id']);
            foreach ($groups as $group) {
                $groupId = $appServerInProduction->addGroup($areaId, $group['name'], 
                    $group['idc_type'], array(
                        'group_code' => $group['group_code'],
                    	'creator' => $group['creator'],
                    	'status' => $group['status']
                    ));
                if ($groupId === false) {
                    $logger->warning("copy group failed: group-{$group['id']}, error-" . 
                        $appServerInProduction->getErrorMessage());
                    continue;
                }
                $appServerInTest->modifyGroup($group['id'], array(
                	'map_id' => $groupId
                ));
                $servers = $appServerInTest->getGroupServers($group['id']);
                foreach ($servers as $server) {
                    $serverId = $appServerInProduction->addServer($groupId, $server['ip'], 
                        $server['alias'], array(
                    		'creator' => $area['creator']
                        ));
                    if ($serverId === false && $appServerInProduction->getErrorNo() == 1) {
                        $logger->warning("ip alias duplicated: server-{$server['id']}");
                        $server['alias'] = $server['alias'] . "_" . $server['id'];
                        $serverId = $appServerInProduction->addServer($groupId, $server['ip'], 
                            $server['alias'], array(
                        		'creator' => $area['creator']
                            ));
                    }
                    if ($serverId === false) {
                        $logger->warning("copy server failed: server-{$server['id']}, error-" . 
                            $appServerInProduction->getErrorMessage());
                        continue;
                    }
                    $appServerInTest->modifyServer($server['id'], array(
                    	'map_id' => $serverId
                    ));
                }
            }
        }
        
        if ($type == 'all' || $type == 'login') {
	        $loginServers = $appServerInTest->getAppLoginServers($appId);
	        foreach ($loginServers as $loginServer) {
	            $loginServerId = $appServerInProduction->addLoginServer($appId, $loginServer['ip'], 
	                $loginServer['alias'], $loginServer['idc_type'], array(
	                	'creator' => $area['creator']
	                ));
	            if ($loginServerId === false && $appServerInProduction->getErrorNo() == 1) {
	                $logger->warning("ip alias duplicated:: login_server-{$loginServer['id']}");
	                $loginServer['alias'] = $loginServer['alias'] . "_" . $loginServer['id'];
	                $loginServerId = $appServerInProduction->addLoginServer($appId, $loginServer['ip'], 
	                    $loginServer['alias'], $loginServer['idc_type'], array(
	                    	'creator' => $area['creator']
	                    ));
	            }
	            if ($loginServerId === false) {
	                $logger->warning("copy login server failed: login_server-{$loginServer['id']}, error-" . 
	                    $appServerInProduction->getErrorMessage());
	                continue;
	            }
	            $appServerInTest->modifyLoginServer($loginServer['id'], array(
	            	'map_id' => $loginServerId
	            ));
	            $loginServerValidTos = $appServerInTest->getLoginServerValidTo($loginServer['id']);
	            foreach ($loginServerValidTos as $loginServerValidTo) {
	                $id = $appServerInProduction->addLoginServerValidTo($loginServerId, 
	                    $appServerInTest->getAreaMapId($loginServerValidTo['valid_to_area']),
	                    $appServerInTest->getGroupMapId($loginServerValidTo['valid_to_group']),
	                    $appServerInTest->getServerMapId($loginServerValidTo['valid_to_server']), array(
	                    	'status' => $loginServerValidTo['status']
	                    ));
	                if ($id === false) {
	                    $logger->warning("copy login server valid row failed: valid_row-{$loginServerValidTo['id']}, error-" . 
	                        $appServerInProduction->getErrorMessage());
	                    continue;
	                }
	                $appServerInTest->modifyLoginServerValidTo($loginServerValidTo['id'], array(
	                	'map_id' => $id
	                ));
	            }
	        }
        }
    
        if ($type == 'all' || $type == 'pay') {
	        $payServers = $appServerInTest->getAppPayServers($appId);
	        foreach ($payServers as $payServer) {
	            $payServerId = $appServerInProduction->addPayServer($appId, $payServer['type'], 
	                $payServer['addr'], $payServer['ip'], $payServer['alias'], $payServer['idc_type'], 
	                array(
	                	'need_confirm' => $payServer['need_confirm'],
	                	'user_id_type' => $payServer['user_id_type'],
	                	'creator' => $payServer['creator']
	                ));
	            if ($payServerId === false && $appServerInProduction->getErrorNo() == 1) {
	                $logger->warning("ip alias duplicated:: pay_server-{$payServer['id']}");
	                $payServer['alias'] = $payServer['alias'] . "_" . $payServer['id'];
	                $payServerId = $appServerInProduction->addPayServer($appId, $payServer['type'], 
	                    $payServer['addr'], $payServer['ip'], $payServer['alias'], $payServer['idc_type'], 
	                    array(
	                    	'need_confirm' => $payServer['need_confirm'],
	                    	'user_id_type' => $payServer['user_id_type'],
	                    	'creator' => $payServer['creator']
	                    ));
	            }
	            if ($payServerId === false) {
	                $logger->warning("copy pay server failed: pay_server-{$payServer['id']}, error-" . 
	                    $appServerInProduction->getErrorMessage());
	                continue;
	            }
	            $appServerInTest->modifyPayServer($payServer['id'], array(
	            	'map_id' => $payServerId
	            ));
	            $payServerValidTos = $appServerInTest->getPayServerValidTo($payServer['id']);
	            foreach ($payServerValidTos as $payServerValidTo) {
	                $id = $appServerInProduction->addPayServerValidTo($payServerId,
	                    $appServerInTest->getAreaMapId($payServerValidTo['valid_to_area']),
	                    $appServerInTest->getGroupMapId($payServerValidTo['valid_to_group']),
	                    $appServerInTest->getServerMapId($payServerValidTo['valid_to_server']), array(
	                    	'status' => $payServerValidTo['status']
	                    ));
	                if ($id === false) {
	                    $logger->warning("copy pay server valid row failed: valid_row-{$payServerValidTo['id']}, error-" . 
	                        $appServerInProduction->getErrorMessage());
	                    continue;
	                }
	                $appServerInTest->modifyPayServerValidTo($payServerValidTo['id'], array(
	                	'map_id' => $id
	                ));
	            }
	        }
        }
        return true;
    }
	
    /**
     * 获取服务器修改，包括游戏、登录和发货三种服务器
     * @param int $appId
     * @param int $env
     * @return array|boolean 返回结果格式如下
     * array(
     *   'gs_changes' => array(...), 游戏服务器修改，格式说明见getGSChanges接口
     *   'ls_changes' => array(...), 登录服务器修改，格式说明见getLSChanges接口
     *   'ps_changes' => array(...)  发货服务器修改，格式说明见getPSChanges接口
     * )
     */
	public static function getChanges($appId, $env) 
	{
		$gsChanges = self::getGSChanges($appId, $env);
		$lsChanges = self::getLSChanges($appId, $env);
		$psChanges = self::getPSChanges($appId, $env);
		return array(
			'gs_changes' => $gsChanges,
			'ls_changes' => $lsChanges,
			'ps_changes' => $psChanges
		);
	}
    
    /**
     * 获取游戏服务器修改，通过比较当前版和上一次同步版得到
     * @param int $appId
     * @param int $env
     * @return array|boolean 返回有修改的服务器列表，类似下面的形式
     * array(
     *   array(						区修改
     *     op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *     old => ...,				原值，没有则为null
     *     new => ...,				新值，没有则为null
     *     group_changes => array(		区下的组修改
     *       op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *       old => ...,				原值，没有则为null
     *       new => ...,				新值，没有则为null
     *       server_changes => array(		组下的服务器修改
     *         op => add|update|delete, 	修改类型，新增、修改或删除
     *         old => ...,					原值，没有则为null
     *         new => ...					新值，没有则为null
     *       )
     *     )
     *   ),
     *   ...
     * )
     */
    public static function getGSChanges($appId, $env, $elder = false, $all = false)
    {
        $logger = self::getLogger();
    	$appServerModel = new OaAppServerModel($env, $logger);
    	$appCfgOrdMod = new OaAppConfigOrderModel($logger);
    	$order = $appCfgOrdMod->getAppLastConfigOrder($appId);
    	if($elder)
    	{
    		$tmp_order = $appCfgOrdMod->getConfigOrderList(array(
	            'app_id' => $appId
	        ), 0, 1, 'create_time DESC', array(
	            array(
	                'key' => 'status',
	                'operation' => '=',
	                'value' => OaAppConfigOrderModel::CONFIG_ORDER_STATUS_IN_OPERATION
	            )
	        ));
	        if($tmp_order)
	        	$order = $tmp_order[0];
    	}
    	if (!is_array($order)) {
    		$logger->err("get last order failed: app-$appId");
    		return false;
    	}
    	$snapshot = $appCfgOrdMod->getAppSnapshot($order['id'], $env, array('area_info', 
    		'group_info', 'server_info'));
    	
    	if($all)
    		$snapshot = array();
    	
    	$oldAreas = $snapshot['area_info'];
    	$newAreas = $appServerModel->getAppAreas($appId, 0, null, $env);
    	$areaChanges = self::_compareRows($oldAreas, $newAreas, 'id', array('name', 
    		'idc_type', 'status'));
    	if ($areaChanges === false) {
    		$logger->err("compare areas failed");
    		return false;
    	}
    	foreach ($areaChanges as $keyArea => &$areaChange) {
    		if ($areaChange['op'] == 'delete') {
    			$areaId = $areaChange['old']['id'];
    			$oldGroups = isset($snapshot['group_info'][$areaId]) ? 
    				$snapshot['group_info'][$areaId] : array();
    			$newGroups = array();
    		} else if ($areaChange['op'] == 'update' || empty($areaChange['op'])) {
    			$areaId = $areaChange['old']['id'];
    			$oldGroups = isset($snapshot['group_info'][$areaId]) ? 
    				$snapshot['group_info'][$areaId] : array();
    			$newGroups = $appServerModel->getAreaGroups($areaId);
    		} else if ($areaChange['op'] == 'add') {
    			$areaId = $areaChange['new']['id'];
    			$oldGroups = array();
    			$newGroups = $appServerModel->getAreaGroups($areaId);
    		}
    		$groupChanges = self::_compareRows($oldGroups, $newGroups, 'id', array('name', 
    			'idc_type', 'status'));
    		if ($groupChanges === false) {
    			$logger->err("compare groups failed");
    			return false;
    		}
    		foreach ($groupChanges as $keyGroup => &$groupChange) {
	    		if ($groupChange['op'] == 'delete') {
	    			$groupId = $groupChange['old']['id'];
	    			$oldServers = isset($snapshot['server_info'][$groupId]) ? 
	    				$snapshot['server_info'][$groupId] : array();
	    			$newServers = array();
	    		} else if ($groupChange['op'] == 'update' || empty($groupChange['op'])) {
	    			$groupId = $groupChange['old']['id'];
	    			$oldServers = isset($snapshot['server_info'][$groupId]) ? 
	    				$snapshot['server_info'][$groupId] : array();
	    			$newServers = $appServerModel->getGroupServers($groupId);
	    		} else if ($groupChange['op'] == 'add') {
	    			$groupId = $groupChange['new']['id'];
	    			$oldServers = array();
	    			$newServers = $appServerModel->getGroupServers($groupId);
	    		}
	    		$serverChanges = self::_compareRows($oldServers, $newServers, 'id', 
	    			array('ip', 'alias'), false);
	    		if ($serverChanges === false) {
	    			$logger->err("compare servers failed");
	    			return false;
	    		}
	    		if (empty($serverChanges) && empty($groupChange['op'])) {
	    			unset($groupChanges[$keyGroup]);
	    		} else {
	    			$groupChange['server_changes'] = $serverChanges;
	    		}
    		}
    		if (empty($groupChanges) && empty($areaChange['op'])) {
    			unset($areaChanges[$keyArea]);
    		} else {
    			$areaChange['group_changes'] = $groupChanges;
    		}
    	}
    	return $areaChanges;
    }

    /**
     * 获取登录服务器修改，通过比较当前版和上一次同步版得到
     * @param int $appId
     * @param int $env
     * @return array|boolean 返回有修改的服务器列表，类似下面的形式
     * array(
     *   array(						登录服务器修改
     *     op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *     old => ...,				原值，没有则为null
     *     new => ...,				新值，没有则为null
     *     va_changes => array(			生效范围修改
     *       op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *       old => ...,				原值，没有则为null
     *       new => ...					新值，没有则为null
     *     )
     *   ),
     *   ...
     * )
     */
    public static function getLSChanges($appId, $env)
    {
        $logger = self::getLogger();
    	$appServerModel = new OaAppServerModel($env, $logger);
    	$appCfgOrdMod = new OaAppConfigOrderModel($logger);
    	$order = $appCfgOrdMod->getAppLastConfigOrder($appId);
    	if (!is_array($order)) {
    		$logger->err("get last order failed: app-$appId");
    		return false;
    	}
    	$snapshot = $appCfgOrdMod->getAppSnapshot($order['id'], $env, array('login_server_info', 
    		'login_server_valid_info'));
    	
    	$oldLoginServers = $snapshot['login_server_info'];
    	$newLoginServers = $appServerModel->getAppLoginServers($appId, $env);
    	$loginServerChanges = self::_compareRows($oldLoginServers, $newLoginServers, 
    		'id', array('ip', 'alias', 'idc_type'));
    	if ($loginServerChanges === false) {
    		$logger->err("compare login servers failed");
    		return false;
    	}
    	foreach ($loginServerChanges as $key => &$loginServerChange) {
    		if ($loginServerChange['op'] == 'delete') {
    			$loginServerId = $loginServerChange['old']['id'];
    			$oldLoginServerVAs = isset($snapshot['login_server_valid_info'][$loginServerId]) ? 
    				$snapshot['login_server_valid_info'][$loginServerId] : array();
    			$newLoginServerVAs = array();
    		} else if ($loginServerChange['op'] == 'update' || empty($loginServerChange['op'])) {
    			$loginServerId = $loginServerChange['old']['id'];
    			$oldLoginServerVAs = isset($snapshot['login_server_valid_info'][$loginServerId]) ? 
    				$snapshot['login_server_valid_info'][$loginServerId] : array();
    			$newLoginServerVAs = $appServerModel->getLoginServerValidTo($loginServerId);
    		} else if ($loginServerChange['op'] == 'add') {
    			$loginServerId = $loginServerChange['new']['id'];
    			$oldLoginServerVAs = array();
    			$newLoginServerVAs = $appServerModel->getLoginServerValidTo($loginServerId);
    		}
    		$loginServerVAChanges = self::_compareRows($oldLoginServerVAs, $newLoginServerVAs, 
    			'id', array('valid_to_area', 'valid_to_group', 'valid_to_server', 
    			'status', 'area_code', 'group_code', 'server_ip_id', 'ip_id'), false);
    		if ($loginServerVAChanges === false) {
    			$logger->err("compare login server valid areas failed");
    			return false;
    		}
    		if (empty($loginServerVAChanges) && empty($loginServerChange['op'])) {
    			unset($loginServerChanges[$key]);
    		} else {
    			$loginServerChange['va_changes'] = $loginServerVAChanges;
    		}
    	}
    	return $loginServerChanges;
    }
    
    /**
     * 获取发货服务器修改，通过比较当前版和上一次同步版得到
     * @param int $appId
     * @param int $env
     * @return array|boolean 返回有修改的服务器列表，类似下面的形式
     * array(
     *   array(						发货服务器修改
     *     op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *     old => ...,				原值，没有则为null
     *     new => ...,				新值，没有则为null
     *     va_changes => array(			生效范围修改
     *       op => add|update|delete,	修改类型，新增、修改或删除，为空表示没有修改
     *       old => ...,				原值，没有则为null
     *       new => ...					新值，没有则为null
     *     )
     *   ),
     *   ...
     * )
     */
    public static function getPSChanges($appId, $env)
    {
        $logger = self::getLogger();
    	$appServerModel = new OaAppServerModel($env, $logger);
    	$appCfgOrdMod = new OaAppConfigOrderModel($logger);
    	$order = $appCfgOrdMod->getAppLastConfigOrder($appId);
    	if (!is_array($order)) {
    		$logger->err("get last order failed: app-$appId");
    		return false;
    	}
    	$snapshot = $appCfgOrdMod->getAppSnapshot($order['id'], $env, array('pay_server_info', 
    		'pay_server_valid_info'));
    	
    	$oldPayServers = $snapshot['pay_server_info'];
    	$newPayServers = $appServerModel->getAppPayServers($appId, $env);
    	$payServerChanges = self::_compareRows($oldPayServers, $newPayServers, 
    		'id', array('type', 'addr', 'ip', 'alias', 'idc_type', 'need_confirm', 
    		'user_id_type'));
    	if ($payServerChanges === false) {
    		$logger->err("compare pay servers failed");
    		return false;
    	}
    	foreach ($payServerChanges as $key => &$payServerChange) {
    		if ($payServerChange['op'] == 'delete') {
    			$payServerId = $payServerChange['old']['id'];
    			$oldPayServerVAs = isset($snapshot['pay_server_valid_info'][$payServerId]) ? 
    				$snapshot['pay_server_valid_info'][$payServerId] : array();
    			$newPayServerVAs = array();
    		} else if ($payServerChange['op'] == 'update' || empty($payServerChange['op'])) {
    			$payServerId = $payServerChange['old']['id'];
    			$oldPayServerVAs = isset($snapshot['pay_server_valid_info'][$payServerId]) ? 
    				$snapshot['pay_server_valid_info'][$payServerId] : array();
    			$newPayServerVAs = $appServerModel->getPayServerValidTo($payServerId);
    		} else if ($payServerChange['op'] == 'add') {
    			$payServerId = $payServerChange['new']['id'];
    			$oldPayServerVAs = array();
    			$newPayServerVAs = $appServerModel->getPayServerValidTo($payServerId);
    		}
    		$payServerVAChanges = self::_compareRows($oldPayServerVAs, $newPayServerVAs, 
    			'id', array('valid_to_area', 'valid_to_group', 'valid_to_server', 
    			'status', 'area_code', 'group_code', 'server_ip_id', 'ip_id'), false);
    		if ($payServerVAChanges === false) {
    			$logger->err("compare pay server valid areas failed");
    			return false;
    		}
    		if (empty($payServerVAChanges) && empty($payServerChange['op'])) {
    			unset($payServerChanges[$key]);
    		} else {
    			$payServerChange['va_changes'] = $payServerVAChanges;
    		}
    	}
    	return $payServerChanges;
    }
    
    private static function _compareRows($oldRows, $newRows, $key, $fields, $returnUnchanged = true)
    {
        if(!$oldRows) $oldRows = array();
        if(!$newRows) $newRows = array();
        $logger = self::getLogger();
    	$rowChanges = array();
    	$oldRow = current($oldRows);
    	$newRow = current($newRows);
    	while (true) {
    		if ($oldRow && (($newRow && ($oldRow[$key] < $newRow[$key])) 
    			|| !$newRow)) {
    			$rowChange = array(
    				'op' => 'delete',
    				'old' => $oldRow,
    				'new' => null
    			);
    			$rowChanges[] = $rowChange;
    			$oldRow = next($oldRows);
    		} else if ($oldRow && $newRow && $oldRow[$key] == $newRow[$key]) {
    			$changed = false;
		    	foreach ($fields as $field) {
		    		if ((isset($oldRow[$field]) && isset($newRow[$field]) && $oldRow[$field] != $newRow[$field]) || 
		    			(isset($oldRow[$field]) && !isset($newRow[$field]) || 
		    			(!isset($oldRow[$field]) && isset($newRow[$field])))) {
		    			$changed = true;
		    			break;
		    		}
		    	}
    			if ($changed) {
    				$rowChange = array(
	    				'op' => 'update',
	    				'old' => $oldRow,
	    				'new' => $newRow
	    			);
    				$rowChanges[] = $rowChange;
    			} else {
    				if ($returnUnchanged) {
	    				$rowChange = array(
		    				'op' => '',
		    				'old' => $oldRow,
		    				'new' => null
		    			);
    					$rowChanges[] = $rowChange;
    				}
    			}
    			$oldRow = next($oldRows);
    			$newRow = next($newRows);
    		} else if ($newRow && (($oldRow && ($oldRow[$key] > $newRow[$key])) 
    			|| !$oldRow)) {
    			$rowChange = array(
    				'op' => 'add',
    				'old' => null,
    				'new' => $newRow
    			);
    			$rowChanges[] = $rowChange;
    			$newRow = next($newRows);
    		} else if (!$oldRow && !$newRow) {
    			break;
    		}
    	}
    	return $rowChanges;
    }
    
    /**
     * 撤销服务器修改，包括游戏、登录和发货服务器
     * @param int $appId
     * @param int $env
     * @param array &$result
     * array(
     *   'gs_changes' => array(	游戏服务器修改，格式说明见getGSChanges接口
     *     array(						区修改
     *       ...
     *       revert_result => array(	撤销结果
     *         errno => ...				错误号，0表示成功，其余表示失败
     *         error => ...				错误信息
     *       ),
     *       group_changes => array(		区下的组修改
     *         array(
     *           ...
     *           revert_result => array(	撤销结果
     *             errno => ...				错误号，0表示成功，其余表示失败
     *             error => ...				错误信息
     *           ),
     *           server_changes => array(		组下的服务器修改
     *             array(
     *               ...
     *               revert_result => array(	撤销结果
     *                 errno => ...				错误号，0表示成功，其余表示失败，其中1表示IP+别名冲突
     *                 error => ...				错误信息
     *               )
     *             ),
     *             ...
     *           )
     *         ),
     *         ...
     *       )
     *     ),
     *     ... 
     *   ),
     *   'ls_changes' => array(	登录服务器修改，格式说明见getLSChanges接口
     *     array(
     *       ...
     *       revert_result => array(	撤销结果
     *         errno => ...				错误号，0表示成功，其余表示失败，其中1表示IP+别名冲突
     *         error => ...				错误信息
     *       ),
     *       va_changes => array(			生效范围修改
     *         array(
     *           ...
     *           revert_result => array(	撤销结果
     *             errno => ...				错误号，0表示成功，其余表示失败
     *             error => ...				错误信息
     *           )
     *         ),
     *         ...
     *       )
     *     ),
     *     ...
     *   ),
     *   'ps_changes' => array(	发货服务器修改，格式说明见getPSChanges接口
     *     array(
     *       ...
     *       revert_result => array(	撤销结果
     *         errno => ...				错误号，0表示成功，其余表示失败，其中1表示IP+别名冲突
     *         error => ...				错误信息
     *       ),
     *       va_changes => array(			生效范围修改
     *         array(
     *           ...
     *           revert_result => array(	撤销结果
     *             errno => ...				错误号，0表示成功，其余表示失败
     *             error => ...				错误信息
     *           )
     *         ),
     *         ...
     *       )
     *     ),
     *     ...
     *   )
     * )
     * @return boolean
     */
    public static function revertChanges($appId, $env, &$result = null)
    {
    	$logger = self::getLogger();
    	$appServerModel = new OaAppServerModel($env, $logger);
    	
    	$ret = true;
    	$areaChanges = self::getGSChanges($appId, $env);
    	if ($areaChanges === false) {
    		$logger->err("get gs changes failed: app-$appId, env-$env");
    		return false;
    	}
    	foreach ($areaChanges as &$areaChange) {
    		$areaChange['revert_result'] = array('errno' => 0, 'error' => '');
    		if ($areaChange['op'] == 'add') {
    			$area = $areaChange['new'];
    			foreach ($areaChange['group_changes'] as &$groupChange) {
    				$groupChange['revert_result'] = array('errno' => 0, 'error' => '');
    				$group = $groupChange['new'];
    				foreach ($groupChange['server_changes'] as &$serverChange) {
    					$serverChange['revert_result'] = array('errno' => 0, 'error' => '');
    					$server = $serverChange['new'];
    					if (!$appServerModel->deleteServer($server['id'])) {
		    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
		    				$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    				if (!$appServerModel->deleteGroup($group['id'])) {
	    				$groupChange['revert_result']['errno'] = $appServerModel->getErrorNo();
	    				$groupChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			if (!$appServerModel->deleteArea($area['id'])) {
    				$areaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$areaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		} else if ($areaChange['op'] == 'update' || empty($areaChange['op'])) {
    			$area = $areaChange['old'];
    			if ($areaChange['op'] == 'update') {
    				$row = $area;
    				unset($row['id']);
    				if (!$appServerModel->modifyArea($area['id'], $row)) {
    					$areaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    					$areaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			foreach ($areaChange['group_changes'] as &$groupChange) {
    				$groupChange['revert_result'] = array('errno' => 0, 'error' => '');
    				if ($groupChange['op'] == 'add') {
    					$group = $groupChange['new'];
	    				foreach ($groupChange['server_changes'] as &$serverChange) {
	    					$serverChange['revert_result'] = array('errno' => 0, 'error' => '');
	    					$server = $serverChange['new'];
	    					if (!$appServerModel->deleteServer($server['id'])) {
			    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    				$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    							$ret = false;
	    					}
	    				}
	    				if (!$appServerModel->deleteGroup($group['id'])) {
		    				$groupChange['revert_result']['errno'] = $appServerModel->getErrorNo();
		    				$groupChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
	    				}
    				} else if ($groupChange['op'] == 'update' || empty($groupChange['op'])) {
    					$group = $groupChange['old'];
    					if ($groupChange['op'] == 'update') {
    						$row = $group;
    						unset($row['id']);
    						if (!$appServerModel->modifyGroup($group['id'], $row)) {
			    				$groupChange['revert_result']['errno'] = $appServerModel->getErrorNo();
		    					$groupChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    							$ret = false;
    						}
    					}
    					foreach ($groupChange['server_changes'] as &$serverChange) {
	    					$serverChange['revert_result'] = array('errno' => 0, 'error' => '');
    						if ($serverChange['op'] == 'add') {
    							$server = $serverChange['new'];
    							if (!$appServerModel->deleteServer($server['id'])) {
				    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    					$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    								$ret = false;
    							}
    						} else if ($serverChange['op'] == 'update') {
    							$server = $serverChange['old'];
    							$row = $server;
    							unset($row['id']);
    							if (!$appServerModel->modifyServer($server['id'], $row)) {
				    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    					$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    								$ret = false;
    							}
    						} else if ($serverChange['op'] == 'delete') {
    							$server = $serverChange['old'];
    							if (!$appServerModel->addServer($server['group_id'], 
    								$server['ip'], $server['alias'], $server)) {
				    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    					$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    								$ret = false;
    							}
    						}
    					}
    				} else if ($groupChange['op'] == 'delete') {
    					$group = $groupChange['old'];
    					if ($appServerModel->addGroup($group['area_id'], $group['name'], 
    						$group['idc_type'], $group)) {
    						foreach ($groupChange['server_changes'] as &$serverChange) {
	    						$serverChange['revert_result'] = array('errno' => 0, 'error' => '');
    							$server = $serverChange['old'];
    							if (!$appServerModel->addServer($server['group_id'], 
    								$server['ip'], $server['alias'], $server)) {
				    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    					$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    								$ret = false;
    							}
    						}
    					} else {
	    					$groupChange['revert_result']['errno'] = $appServerModel->getErrorNo();
		    				$groupChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			}
    		} else if ($areaChange['op'] == 'delete') {
    			$area = $areaChange['old'];
    			if ($appServerModel->addArea($appId, $area['name'], $area['idc_type'], 
    				$area)) {
    				foreach ($areaChange['group_changes'] as &$groupChange) {
    					$groupChange['revert_result'] = array('errno' => 0, 'error' => '');
    					$group = $groupChange['old'];
    					if ($appServerModel->addGroup($group['area_id'], $group['name'], 
    						$group['idc_type'], $group)) {
    						foreach ($groupChange['server_changes'] as &$serverChange) {
	    						$serverChange['revert_result'] = array('errno' => 0, 'error' => '');
    							$server = $serverChange['old'];
    							if (!$appServerModel->addServer($server['group_id'], 
    								$server['ip'], $server['alias'], $server)) {
				    				$serverChange['revert_result']['errno'] = $appServerModel->getErrorNo();
			    					$serverChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    								$ret = false;
    							}
    						}
    					} else {
	    					$groupChange['revert_result']['errno'] = $appServerModel->getErrorNo();
		    				$groupChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			} else {
    				$areaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$areaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		}
    	}
    
    	$lsChanges = self::getLSChanges($appId, $env);
    	if ($lsChanges === false) {
    		$logger->err("get ls changes failed: app-$appId, env-$env");
    		return false;
    	}
    	foreach ($lsChanges as &$lsChange) {
    		$lsChange['revert_result'] = array('errno' => 0, 'error' => '');
    		if ($lsChange['op'] == 'add') {
    			$ls = $lsChange['new'];
    			foreach ($lsChange['va_changes'] as &$vaChange) {
		    		$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
		    		$va = $vaChange['new'];
    				if (!$appServerModel->deleteLoginServerValidTo($va['id'])) {
    					$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    					$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			if (!$appServerModel->deleteLoginServer($ls['id'])) {
    				$lsChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$lsChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		} else if ($lsChange['op'] == 'update' || empty($lsChange['op'])) {
    			$ls = $lsChange['old'];
    			if ($lsChange['op'] == 'update') {
    				$row = $ls;
    				unset($row['id']);
    				if (!$appServerModel->modifyLoginServer($ls['id'], $row)) {
	    				$lsChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    					$lsChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			foreach ($lsChange['va_changes'] as &$vaChange) {
		    		$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
    				if ($vaChange['op'] == 'add') {
    					$va = $vaChange['new'];
    					if (!$appServerModel->deleteLoginServerValidTo($va['id'])) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				} else if ($vaChange['op'] == 'update') {
    					$va = $vaChange['old'];
    					$row = $va;
    					unset($row['id']);
    					if (!$appServerModel->modifyLoginServerValidTo($va['id'], $row)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				} else if ($vaChange['op'] == 'delete') {
    					$va = $vaChange['old'];
    					if (!$appServerModel->addLoginServerValidTo($va['login_server_id'], 
    						$va['valid_to_area'], $va['valid_to_group'], $va['valid_to_server'], 
    						$va)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			}
    		} else if ($lsChange['op'] == 'delete') {
    			$ls = $lsChange['old'];
    			if ($appServerModel->addLoginServer($ls['app_id'], $ls['ip'], 
    				$ls['alias'], $ls['idc_type'], $ls)) {
    				foreach ($lsChange['va_changes'] as &$vaChange) {
		    			$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
    					$va = $vaChange['old'];
    					if (!$appServerModel->addLoginServerValidTo($va['login_server_id'], 
    						$va['valid_to_area'], $va['valid_to_group'], $va['valid_to_server'], 
    						$va)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			} else {
    				$lsChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$lsChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		}
    	}
    
    
    	$psChanges = self::getPSChanges($appId, $env);
    	if ($psChanges === false) {
    		$logger->err("get ps changes failed: app-$appId, env-$env");
    		return false;
    	}
    	foreach ($psChanges as &$psChange) {
    		$psChange['revert_result'] = array('errno' => 0, 'error' => '');
    		if ($psChange['op'] == 'add') {
    			$ps = $psChange['new'];
    			foreach ($psChange['va_changes'] as &$vaChange) {
    				$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
    				$va = $vaChange['new'];
    				if (!$appServerModel->deletePayServerValidTo($va['id'])) {
    					$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    					$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			if (!$appServerModel->deletePayServer($ps['id'])) {
    				$psChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$psChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		} else if ($psChange['op'] == 'update' || empty($psChange['op'])) {
    			$ps = $psChange['old'];
    			if ($psChange['op'] == 'update') {
    				$row = $ps;
    				unset($row['id']);
    				if (!$appServerModel->modifyPayServer($ps['id'], $row)) {
	    				$psChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    					$psChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    					$ret = false;
    				}
    			}
    			foreach ($psChange['va_changes'] as &$vaChange) {
    				$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
    				if ($vaChange['op'] == 'add') {
    					$va = $vaChange['new'];
    					if (!$appServerModel->deletePayServerValidTo($va['id'])) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				} else if ($vaChange['op'] == 'update') {
    					$va = $vaChange['old'];
    					$row = $va;
    					unset($row['id']);
    					if (!$appServerModel->modifyPayServerValidTo($va['id'], $row)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				} else if ($vaChange['op'] == 'delete') {
    					$va = $vaChange['old'];
    					if (!$appServerModel->addPayServerValidTo($va['pay_server_id'], 
    						$va['valid_to_area'], $va['valid_to_group'], $va['valid_to_server'], 
    						$va)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			}
    		} else if ($psChange['op'] == 'delete') {
    			$ps = $psChange['old'];
    			if ($appServerModel->addPayServer($ps['app_id'], $ps['type'], $ps['addr'], 
    				$ps['ip'], $ps['alias'], $ps['idc_type'], $ps)) {
    				foreach ($psChange['va_changes'] as &$vaChange) {
    					$vaChange['revert_result'] = array('errno' => 0, 'error' => '');
    					$va = $vaChange['old'];
    					if (!$appServerModel->addPayServerValidTo($va['pay_server_id'], 
    						$va['valid_to_area'], $va['valid_to_group'], $va['valid_to_server'], 
    						$va)) {
		    				$vaChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    						$vaChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    						$ret = false;
    					}
    				}
    			} else {
    				$psChange['revert_result']['errno'] = $appServerModel->getErrorNo();
    				$psChange['revert_result']['error'] = $appServerModel->getErrorMessage();
    				$ret = false;
    			}
    		}
    	}
    	
    	if (!is_null($result)) {
	    	$result = array(
	    		'gs_changes' => $areaChanges,
				'ls_changes' => $lsChanges,
				'ps_changes' => $psChanges
	    	);
    	}
    	return $ret;
    }
    
    /**
     * 增加连调分区，同时写入正式环境
     * @param int $appId
     * @param string $name
     * @param int $idcType
     * @param array $row
     * @return int|boolean 如果分区代码重复，设置错误号1；分区代码超过999，设置错误号2；名称重复，设置错误号3
     */
    public static function addAreaBoth($appId, $name, $idcType = 0, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_TEST;
        $areaId = $appServerModel->addArea($appId, $name, $idcType, $row, true);
        if ($areaId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_PRODUCTION;
        $areaIdInPro = $appServerModel->addArea($appId, $name, $idcType, $row, true);
        if ($areaIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deleteArea($areaId, true);
            return false;
        } else {
            $appServerModel->modifyArea($areaId, array(
                'map_id' => $areaIdInPro
            ));
        }
        return $areaId;
    }
    
    /**
     * 更新连调分区，同时写入正式环境
     * @param int $areaId
     * @param array $row
     * @return boolean 如果有修改名称且名称重复，设置错误号1
     */
    public static function modifyAreaBoth($areaId, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $area = $appServerModel->getArea($areaId);
        if (!is_array($area)) {
            $logger->err("area not exists: area-$areaId");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $area[$key];
        }
        if (!$appServerModel->modifyArea($areaId, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->modifyArea($area['map_id'], $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyArea($areaId, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调分区，同时写入正式环境
     * @param int $areaId
     * @return boolean
     */
    public static function deleteAreaBoth($areaId)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $area = $appServerModel->getArea($areaId);
        if (!is_array($area)) {
            $logger->err("area not exists: area-$areaId");
            return false;
        }
        if (!$appServerModel->deleteArea($areaId, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deleteArea($area['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addArea($area['app_id'], $area['name'], $area['idc_type'], 
            	$area, true);
            return false;
        }
        return true;
    }
    
    /**
     * 增加连调分组，同时写入正式环境
     * @param int $areaId
     * @param string $name
     * @param string $idcType
     * @param array $row
     * @return int|boolean 如果分组代码重复，设置错误号1；分组代码超过999，设置错误号2；如果名称重复，设置错误号3
     */
    public static function addGroupBoth($areaId, $name, $idcType = 0, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $area = $appServerModel->getArea($areaId);
        if (!is_array($area)) {
            $logger->err("area not exists: area-$areaId");
            return false;
        }
        $groupId = $appServerModel->addGroup($areaId, $name, $idcType, $row, true);
        if ($groupId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $groupIdInPro = $appServerModel->addGroup($area['map_id'], $name, $idcType, 
        	$row, true);
        if ($groupIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deleteGroup($groupId, true);
            return false;
        } else {
            $appServerModel->modifyGroup($groupId, array(
                'map_id' => $groupIdInPro
            ));
        }
        return $groupId;
    }
    
    /**
     * 更新连调分组，同时写入正式环境
     * @param int $groupId
     * @param array $row
     * @return boolean 如果有修改组名且组名重复，设置错误号1
     */
    public static function modifyGroupBoth($groupId, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $group = $appServerModel->getGroup($groupId);
        if (!is_array($group)) {
            $logger->err("group not exists: group-$groupId");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $group[$key];
        }
        if (!$appServerModel->modifyGroup($groupId, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->modifyGroup($group['map_id'], $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyGroup($groupId, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调分组，同时写入正式环境
     * @param int $groupId
     * @return boolean
     */
    public static function deleteGroupBoth($groupId)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $group = $appServerModel->getGroup($groupId);
        if (!is_array($group)) {
            $logger->err("group not exists: group-$groupId");
            return false;
        }
        if (!$appServerModel->deleteGroup($groupId, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deleteGroup($group['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addGroup($group['area_id'], $group['name'], $group['idc_type'], 
            	$group, true);
            return false;
        }
        return true;
    }
    
    /**
     * 增加连调服务器，同时写入正式环境
     * @param int $groupId
     * @param string $ip
     * @param string $alias
     * @param array $row
     * @return int|boolean ip+alias重复时，设置错误号1
     */
    public static function addServerBoth($groupId, $ip, $alias, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $group = $appServerModel->getGroup($groupId);
        if (!is_array($group)) {
            $logger->err("group not exists: group-$groupId");
            return false;
        }
        $serverId = $appServerModel->addServer($groupId, $ip, $alias, $row, true);
        if ($serverId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $serverIdInPro = $appServerModel->addServer($group['map_id'], $ip, $alias, 
        	$row, true);
        if ($serverIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deleteServer($serverId, true);
            return false;
        } else {
            $appServerModel->modifyServer($serverId, array(
                'map_id' => $serverIdInPro
            ));
        }
        return $serverId;
    }
    
    /**
     * 更新连调服务器，同时写入正式环境
     * @param int $serverId
     * @param array $row
     * @return boolean 如果跟已有重复，设置错误号1
     */
    public static function modifyServerBoth($serverId, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $server = $appServerModel->getServer($serverId);
        if (!is_array($server)) {
            $logger->err("server not exists: server-$serverId");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $server[$key];
        }
        if (!$appServerModel->modifyServer($serverId, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->modifyServer($server['map_id'], $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyServer($serverId, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调服务器，同时写入正式环境
     * @param int $serverId
     * @return boolean
     */
    public static function deleteServerBoth($serverId)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $server = $appServerModel->getServer($serverId);
        if (!is_array($server)) {
            $logger->err("server not exists: server-$serverId");
            return false;
        }
        if (!$appServerModel->deleteServer($serverId, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deleteServer($server['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addServer($server['group_id'], $server['ip'], $server['alias'], 
            	$server, true);
            return false;
        }
        return true;
    }
    
    /**
     * 增加连调登录服务器，同时写入正式环境
     * @param int $appId
     * @param string $ip
     * @param string $alias
     * @param int $idcType
     * @param array $row
     * @return int|boolean ip+alias重复时，设置错误号1
     */
    public static function addLoginServerBoth($appId, $ip, $alias, $idcType, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_TEST;
        $loginServerId = $appServerModel->addLoginServer($appId, $ip, $alias, $idcType, 
        	$row, true);
        if ($loginServerId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_PRODUCTION;
        $loginServerIdInPro = $appServerModel->addLoginServer($appId, $ip, $alias, 
        	$idcType, $row, true);
        if ($loginServerIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deleteLoginServer($loginServerId, true);
            return false;
        } else {
            $appServerModel->modifyLoginServer($loginServerId, array(
                'map_id' => $loginServerIdInPro
            ));
        }
        return $loginServerId;
    }
    
    /**
     * 更新连调登录服务器，同时写入正式环境
     * @param int $loginServerId
     * @param array $row
     * @return boolean 如果ip+alias重复，设置错误号1
     */
    public static function modifyLoginServerBoth($loginServerId, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $loginServer = $appServerModel->getLoginServer($loginServerId);
        if (!is_array($loginServer)) {
            $logger->err("login server not exists: login_server-$loginServerId");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $loginServer[$key];
        }
        if (!$appServerModel->modifyLoginServer($loginServerId, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->modifyLoginServer($loginServer['map_id'], $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyLoginServer($loginServerId, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调登录服务器，同时写入正式环境
     * @param int $loginServerId
     * @return boolean
     */
    public static function deleteLoginServerBoth($loginServerId)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $loginServer = $appServerModel->getLoginServer($loginServerId);
        if (!is_array($loginServer)) {
            $logger->err("login server not exists: login_server-$loginServerId");
            return false;
        }
        if (!$appServerModel->deleteLoginServer($loginServerId, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deleteLoginServer($loginServer['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addLoginServer($loginServer['app_id'], $loginServer['ip'], 
            	$loginServer['alias'], $loginServer['idc_type'], $loginServer, true);
            return false;
        }
        return true;
    }
    
    /**
     * 更新连调登录服务器生效范围，同步写入正式环境
     * @param int $loginServerId
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param array $row
     * @return int|boolean 如果该生效范围已对该登录服务器配置过，设置错误号1
     */
    public static function addLoginServerValidToBoth($loginServerId, $validToArea, $validToGroup, 
        $validToServer, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validId = $appServerModel->addLoginServerValidTo($loginServerId, $validToArea, 
        	$validToGroup, $validToServer, $row, true);
        if ($validId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $loginServerId = $appServerModel->getLoginServerMapId($loginServerId);
        $validToArea = $appServerModel->getAreaMapId($validToArea);
        $validToGroup = $appServerModel->getGroupMapId($validToGroup);
        $validToServer = $appServerModel->getServerMapId($validToServer);
        $validIdInPro = $appServerModel->addLoginServerValidTo($loginServerId, 
        	$validToArea, $validToGroup, $validToServer, $row, true);
        if ($validIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deleteLoginServerValidTo($validId, true);
            return false;
        } else {
            $appServerModel->modifyLoginServerValidTo($validId, array(
                'map_id' => $validIdInPro
            ));
        }
        return $validId;
    }
    
    /**
     * 更新连调登录服务器生效范围，同时写入正式环境
     * @param int $id
     * @param array $row
     * @return boolean 如果生效范围发生冲突，设置错误号1；ip、alias冲突，设置错误号2
     */
    public static function modifyLoginServerValidToBoth($id, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validRow = $appServerModel->getLoginServerValidToById($id);
        if (!is_array($validRow)) {
            $logger->err("login server valid not exists: valid_row-$id");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $validRow[$key];
        }
        if (!$appServerModel->modifyLoginServerValidTo($id, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $rowInPro = $row;
        if (isset($row['valid_to_area'])) {
            $rowInPro['valid_to_area'] = $appServerModel->getAreaMapId($row['valid_to_area']);
        }
        if (isset($row['valid_to_group'])) {
            $rowInPro['valid_to_group'] = $appServerModel->getGroupMapId($row['valid_to_group']);
        }
        if (isset($row['valid_to_server'])) {
            $rowInPro['valid_to_server'] = $appServerModel->getServerMapId($row['valid_to_server']);
        }
        if (isset($row['login_server_id'])) {
            $rowInPro['login_server_id'] = $appServerModel->getLoginServerMapId($row['login_server_id']);
        }
        if (!$appServerModel->modifyLoginServerValidTo($validRow['map_id'], $rowInPro, 
        	true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyLoginServerValidTo($id, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调登录服务器生效范围，同时写入正式环境
     * @param int $id
     * @return boolean
     */
    public static function deleteLoginServerValidToBoth($id)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validRow = $appServerModel->getLoginServerValidToById($id);
        if (!is_array($validRow)) {
            $logger->err("login server valid not exists: valid_row-$id");
            return false;
        }
        if (!$appServerModel->deleteLoginServerValidTo($id, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deleteLoginServerValidTo($validRow['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addLoginServerValidTo($validRow['login_server_id'], 
            	$validRow['valid_to_area'], $validRow['valid_to_group'], 
            	$validRow['valid_to_server'], $validRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 增加连调充值服务器，同时写入正式环境
     * @param int $type
     * @param string $addr
     * @return int
     */
    public static function addPayServerBoth($appId, $type, $addr, $ip, $alias, 
        $idcType, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_TEST;
        $payServerId = $appServerModel->addPayServer($appId, $type, $addr, $ip, 
        	$alias, $idcType, $row, true);
        if ($payServerId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $row['environment'] = OaAppModel::APP_CONFIG_ENV_PRODUCTION;
        $payServerIdInPro = $appServerModel->addPayServer($appId, $type, $addr, $ip, 
        	$alias, $idcType, $row, true);
        if ($payServerIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deletePayServer($payServerId, true);
            return false;
        } else {
            $appServerModel->modifyPayServer($payServerId, array(
                'map_id' => $payServerIdInPro
            ));
        }
        return $payServerId;
    }
    
    /**
     * 更新连调充值服务器，同时写入正式环境
     * @param int $payServerId
     * @param array $row
     * @return boolean 如果ip+alias重复，设置错误号1
     */
    public static function modifyPayServerBoth($payServerId, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $payServer = $appServerModel->getPayServer($payServerId);
        if (!is_array($payServer)) {
            $logger->err("pay server not exists: pay_server-$payServerId");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $payServer[$key];
        }
        if (!$appServerModel->modifyPayServer($payServerId, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->modifyPayServer($payServer['map_id'], $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyPayServer($payServerId, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调充值服务器，同时写入正式环境
     * @param int $payServerId
     * @return boolean
     */
    public static function deletePayServerBoth($payServerId)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $payServer = $appServerModel->getPayServer($payServerId);
        if (!is_array($payServer)) {
            $logger->err("pay server not exists: pay_server-$payServerId");
            return false;
        }
        if (!$appServerModel->deletePayServer($payServerId, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deletePayServer($payServer['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addPayServer($payServer['app_id'], $payServer['type'], 
            	$payServer['addr'], $payServer['ip'], $payServer['alias'], $payServer['idc_type'], 
            	$payServer, true);
            return false;
        }
        return true;
    }
    
    /**
     * 更新连调充值服务器生效范围，同步写入正式环境
     * @param int $payServerId
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param array $row
     * @return int|boolean 如果该生效范围已经配置过，设置错误号1
     */
    public static function addPayServerValidToBoth($payServerId, $validToArea, $validToGroup, 
        $validToServer, $row = array())
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validId = $appServerModel->addPayServerValidTo($payServerId, $validToArea, 
        	$validToGroup, $validToServer, $row, true);
        if ($validId === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $payServerId = $appServerModel->getPayServerMapId($payServerId);
        $validToArea = $appServerModel->getAreaMapId($validToArea);
        $validToGroup = $appServerModel->getGroupMapId($validToGroup);
        $validToServer = $appServerModel->getServerMapId($validToServer);
        $validIdInPro = $appServerModel->addPayServerValidTo($payServerId, $validToArea, 
        	$validToGroup, $validToServer, $row, true);
        if ($validIdInPro === false) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->deletePayServerValidTo($validId, true);
            return false;
        } else {
            $appServerModel->modifyPayServerValidTo($validId, array(
                'map_id' => $validIdInPro
            ));
        }
        return $validId;
    }
    
    /**
     * 更新连调充值服务器生效范围，同时写入正式环境
     * @param int $id
     * @param array $row
     * @return boolean 如果生效范围发生冲突，设置错误号1；ip、alias冲突，设置错误号2
     */
    public static function modifyPayServerValidToBoth($id, $row)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validRow = $appServerModel->getPayServerValidToById($id);
        if (!is_array($validRow)) {
            $logger->err("pay server valid not exists, valid_row-$id");
            return false;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
            $oldRow[$key] = $validRow[$key];
        }
        if (!$appServerModel->modifyPayServerValidTo($id, $row, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        $rowInPro = $row;
        if (isset($row['valid_to_area'])) {
            $rowInPro['valid_to_area'] = $appServerModel->getAreaMapId($row['valid_to_area']);
        }
        if (isset($row['valid_to_group'])) {
            $rowInPro['valid_to_group'] = $appServerModel->getGroupMapId($row['valid_to_group']);
        }
        if (isset($row['valid_to_server'])) {
            $rowInPro['valid_to_server'] = $appServerModel->getServerMapId($row['valid_to_server']);
        }
        if (isset($row['pay_server_id'])) {
            $rowInPro['pay_server_id'] = $appServerModel->getPayServerMapId($row['pay_server_id']);
        }
        if (!$appServerModel->modifyPayServerValidTo($validRow['map_id'], $rowInPro, 
        	true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->modifyPayServerValidTo($id, $oldRow, true);
            return false;
        }
        return true;
    }
    
    /**
     * 删除连调充值服务器生效范围，同时写入正式环境
     * @param int $id
     * @return boolean
     */
    public static function deletePayServerValidToBoth($id)
    {
        $logger = self::getLogger();
        $appServerModel = new OaAppServerModel(OaAppModel::APP_CONFIG_ENV_TEST, $logger);
        $validRow = $appServerModel->getPayServerValidToById($id);
        if (!is_array($validRow)) {
            $logger->err("pay server valid not exists, valid_row-$id");
            return false;
        }
        if (!$appServerModel->deletePayServerValidTo($id, true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            return false;
        }
        if (!$appServerModel->deletePayServerValidTo($validRow['map_id'], true)) {
            self::setError($appServerModel->getErrorNo(), $appServerModel->getErrorMessage());
            $appServerModel->addPayServerValidTo($validRow['pay_server_id'], $validRow['valid_to_area'], 
            	$validRow['valid_to_group'], $validRow['valid_to_server'], $validRow, 
            	true);
            return false;
        }
        return true;
    }
}